#include "Model.hpp"
 #include "string"
using namespace std;

Model::Model()
{
    _observer = NULL;
    _workingTree = new Tree();
}

void Model::setObserver(Observer* observer)
{
    _observer = observer;
}

void Model::pushOldTree()
{
    if(_workingTree)
    {
        _previousTrees.push(_workingTree);
        _workingTree = new Tree(*_workingTree);
        while(!_cancelledTrees.empty())
        {
            delete _cancelledTrees.top();
            _cancelledTrees.pop();
        }
        _observer->notifyChanges();
    }
}

void Model::undo()
{
    if(canUndo())
    {
        Tree* t = _previousTrees.top();
        _previousTrees.pop();
        _cancelledTrees.push(_workingTree);
        _workingTree = t;
        _observer->notifyChanges();
    }
}

void Model::redo()
{
    if(canRedo())
    {
        Tree* t = _cancelledTrees.top();
        _cancelledTrees.pop();
        _previousTrees.push(_workingTree);
        _workingTree = t;
        _observer->notifyChanges();
    }
}

bool Model::canUndo() const
{
    return !_previousTrees.empty();
}

bool Model::canRedo() const
{
    return !_cancelledTrees.empty();
}

bool Model::isSelectionDeletable() const
{
    return _workingTree->_selection
        && _workingTree->_selection->getFather();
}

void Model::deleteSelection()
{
    if(_workingTree)
    {
        _workingTree->deleteSelectedNodes();
        _observer->notifyChanges();
    }
}


bool Model::canAddChildToSelection()
{
    return _workingTree->_selection;
}

void Model::addChildToSelection()
{
    if(canAddChildToSelection())
    {
        Node* newNode = new Node();
        _workingTree->_selection->addChild(newNode);
        _workingTree->_selection = newNode;
        _observer->notifyChanges();
    }
}

bool Model::canAddSiblingToSelection() const
{
    return _workingTree->_selection
       && (_workingTree->_root != _workingTree->_selection);
}

void Model::addSiblingToSelection()
{
    if(canAddSiblingToSelection())
    {
        Node* newNode = new Node();
        _workingTree->_selection->addLeftSibling(newNode);
        _workingTree->_selection = newNode;
        _observer->notifyChanges();
    }
}

bool Model::canChangeSelectionSettings() const
{
    return _workingTree->_selection;
}

void Model::changeSelectionSettings(const std::string& newName,
                                    Node::NodeType newType)
{
    if(_workingTree->_selection)
    {
        _workingTree->_selection->setName(newName);
        _workingTree->_selection->setType(newType);
        _observer->notifyChanges();
    }
}

const Tree *const Model::getWorkingTree() const
{
    return _workingTree;
}

const Node* const Model::getSelection() const
{
    return _workingTree->_selection;
}


void Model::selectNode(int x, int y)
{
    if (_workingTree != NULL) {
        _workingTree->selectNode(x,y);
        _observer->notifyChanges();
    }
}

string const nomFichier("arbre.txt");
#include <sstream>
#include<stdio.h>
#include <iostream>
#include <fstream>
void Model::save(){


    std::ostringstream out;
    _workingTree->toString(out);
    ofstream monFlux(nomFichier.c_str());
    monFlux << out.str();
}

void Model::open(){
    ifstream monFlux(nomFichier.c_str());
    _workingTree->open(monFlux);
}



void Model::moveSelectedNodesGraphically(int dx, int dy)
{
    _workingTree->moveSelectedNodesGraphically(dx,dy);
    _observer->notifyChanges();
}

bool Model::canRedrawSubtree() const
{
    return _workingTree;
}

void Model::redrawTree()
{
    if(_workingTree)
    {
        _workingTree->redraw();
        _observer->notifyChanges();
    }
}

void Model::manageIterative()
{
    _workingTree->_selection->setIterative();
}

void Model::manageOptional()
{
    _workingTree->_selection->setOptional();
}

bool Model::canChangeSelectionRelationType() const
{
    return _workingTree
        && _workingTree->_selection
        && _workingTree->_selection->getRightSibling();
}

void Model::setSelectionRelationType(Node::RelationType rType)
{
    if(canChangeSelectionRelationType())
        _workingTree->_selection->setRelationType(rType);
}

void Model::newtree(){
    delete _workingTree;
    _workingTree = new Tree();
    _observer->notifyChanges();
}

